/*
	Consumers and Producers are divided into work groups (chips)
	A producer inserts tasks only to containers in its chip 
	A consumer first tries to retrieve tasks from the container in its chip.
	If these containers are empty, the consumer traverses the other chips in a random order.
	If retrieval from all chips failed, NULL is returned 
	Association of producers and consumers to the chips is determined by producerToChip and ConsumerToChip mappings in Config
*/

#ifndef CHIPAWARECONTAINER_H_
#define CHIPAWARECONTAINER_H_
#include "Chip.h"
#include "Config.h"

class ChipAwareContainer : public TaskContainer{

	/* array of chips */
	Chip** chips;
	
	/* number of chips */
	int chipsNum;
	
	/* thread-local variable indicating the number of times a consumer tries performs access to a chip other than its own */
	static __thread int exitsNum;
	
	/* thread-local flag indicating whether a random seed has been initialized by the thread */
	static __thread bool hasRandomSeed;
	
	
	static __thread int consumerId;
	static __thread int producerId;
	
	/* an array holding the number of consumers registered at each chip */
	int* chipRegistrations;
	
public:
	ChipAwareContainer(int maxConsumersPerChip);
	virtual ~ChipAwareContainer();
	Task* get(Statistics* stat);
	Task* getFromChip(Chip* chip, Statistics* stat);  // retrieve a task from a given chip 
	void put(Task* task, Statistics* stat);
	void registerConsumer(int id);
	void registerProducer(int id);
	void init();   //set chips with no consumers to NULL 
	// void setConsumersNum(int consumersNum);
	int getDebugInfo(){return 0;}	
	int getExitsStatistics(){return exitsNum;}
};
#endif  /* CHIPAWARECONTAINER_H_ */